#ifndef _EVALUATE_H
#define _EVALUATE_H
#include <stdio.h>
#define MIN(a,b) ((a<b)?(a):(b))
#define MAX(a,b) ((a>b)?(a):(b))

#define ABS(a) ((a > 0)?(a):(-(a)))
#define TWOPAWNMOVE
// for finding legal moves for each piece
#define RLOFFSET_MAX 4
#define BLOFFSET_MAX 4
#define QLOFFSET_MAX 8
#define NLOFFSET_MAX 8
#define KLOFFSET_MAX 8
#ifdef TWOPAWNMOVE
#define PLOFFSET_MAX 4
#else
#define PLOFFSET_MAX 3
#endif

#define PAWN 0
#define KNIGHT 1
#define BISHOP 2
#define ROOK 3
#define QUEEN 4
#define KING 5

#define TRUE 1
#define FALSE 0

#define ENABLE_DEBUG
extern FILE *fedbg;

#ifdef ENABLE_DEBUG

#define DEBUG_PRINT(a,...) fprintf(fedbg,a,##__VA_ARGS__)
#define DEBUG_INIT(filename) ((fedbg = fopen(filename,"a")))

#else

#define DEBUG_PRINT(a) 
#define DEBUG_INIT(filename) 

#endif

typedef struct __pieceState{
	int piecetype;
	int playeridx;
	int squareidx;
	int isalive;
	int *legaloffsetTab;
	int numlegaloffsets;
	float vint;
	float vdyn;
	float vpos;
	float wint;
	float wdyn;
	float wpos;
	float tot_value;
	int legalMoves[64];
	int numLegal;
	int influence_squarepos[64];
	int influence_numsquares;	
	int computeInteraction;

	int enemyAttackedidxflag[32]; 
	int enemyAttackedVal[32];
	int numAttacked;

	int enemyAttackingidxflag[32]; 
	int enemyAttackingVal[32];
	int numAttacking;

	int friendDefendedidxflag[32]; 
	int friendDefendedVal[32]; 
	int numDefended;

	int friendDefendingidxflag[32]; 
	int friendDefendingVal[32]; 
	int numDefending;

}pieceState;

typedef struct __boardState{
	pieceState pieces[32];	
	int board[64];
	int influence_pieceidx[64][32]; // pieces whose influence passes through a given square (starts from the piece itself and ends either at another piece or board edge)
	int influence_piecepos[64][32]; // all those pieces whose path passes through a given square
	int influence_numpieces[64];   // number of pieces which are affected by piece present on a given sqaure
	float total_score;
	int hasRookMoved[2][2];
	int hasKingMoved[2];
}boardState;

typedef struct __playerObj{
	int playerid;
}playerObj;

typedef struct __moveDesc{
	int pieceidx;
	int oldpos;
	int newpos;
	int validate;

	int pieceidx2;
	int oldpos2;
	int newpos2;
	int validate2;
}moveDesc;

typedef struct {
	float pawn_val;
	float knight_val;
	float bishop_val;
	float rook_val;
	float queen_val;
	float king_val;
	float a1;
	float a2;
	float wpos;
	float wint;
	float wdyn;
}params;

#define isempty(x) ((x==-1)?(1):(0))
#define areFriends(pbs, idx1, idx2) ((pbs->pieces[idx1].playeridx == pbs->pieces[idx2].playeridx))
#define hasInfluence(pbs,pieceidx, squarepos)  ((pbs->pieces[pieceidx].influence_squarepos[squarepos]))
#define isbounded(x) (((x) >= 0)&&((x) <= 63))
#define rowlowerbound(x) (8*(x/8))
#define rowupperbound(x) (rowlowerbound(x)+7)
#define columnlowerbound(x) (x%8)
#define columnupperbound(x) (56 + columnlowerbound(x))
#define isvalidpos(x,newpos) ((isbounded(newpos))&&(ABS(columnlowerbound(x)-columnlowerbound(newpos)) <= 2))
#define isWithinBoard(currPos) ((currPos >= 0)&&(currPos <= 63))
#define isalive(pbs,pieceidx) ((pbs->pieces[pieceidx].isalive))
#define isAttacked(pbs,pieceidx,attackeridx) ((pbs->pieces[attackeridx].enemyAttackedidxflag[pieceidx]))
#define isDefended(pbs,pieceidx,defenderidx) ((pbs->pieces[defenderidx].friendDefendedidxflag[pieceidx]))
#endif